/**
 * 
 */
package com.sip.comserver.communication.utils;

import java.sql.Date;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.StringTokenizer;

import javax.sql.rowset.spi.SyncResolver;

/**
 * @author Dhanushka Ariyasingha.
 *
 */
public class CommonUtils {
	
    private static int rightColumn = 60;

    private static int leftColumn = 60;
    
    private static int intend = 0;
    
    private static String stringCash = new String();
    
    private static String delimiterLevel1 = "\\|";
    
    private static String delimiterLevel2 = ":";
    
    private static String printHeading = "";
    
    private static String printString = "";
    
    public synchronized static String find(final String dataPattern, final String key) throws Exception {

        String value = null;
        if (null == dataPattern)
            throwCommonUtilityException("Data pattern should not be null value. patter should be in <key>" + delimiterLevel1 + "<value>.");

        final StringTokenizer tokenizer = new StringTokenizer(dataPattern, delimiterLevel1);

        while (tokenizer.hasMoreTokens()) {

            final String nextToken = tokenizer.nextToken();
            validate(nextToken);
            final String tokenKey = getKey(nextToken);
            final String tokenValue = getValue(nextToken);

            if (key.trim().equalsIgnoreCase(tokenKey.trim())){
                reset();        
                return tokenValue.trim();
            }
        }
        
        reset();

        if (null == value)
            throwCommonUtilityException("Search string : < " + key + " > not found in the pattern [ " + dataPattern + " ]");

        return value;
    }

    //SEGMENT_ID:segS1|CATAGORY:segmentation|DISCRIPTION:des|CONSUMER_TYPE:Consumer|ACCESS_TYPE_TYPE:include|ACCESS_TYPE_VALUE :fios,dsl|STATE_TYPE:include|STATE_VALUE:DC,CT,PA
	public static String find(final String key) throws Exception {
	    
		return find(stringCash, key);
	}

    public static String split(final String stringPattaren, final int index) {

        return stringPattaren.split(delimiterLevel1)[index];
    }
    
	public static void register(final String value) {
		stringCash = new String(value);
	}

    public static void registerHeading(final String heading, final int intendValue) {

        intend = intendValue;
        registerHeading(heading);
    }
	
    public static void registerHeading(final String heading) {

        printHeading = heading;
    }
    
    public static void appendHeader(final String appendString) {

        printHeading = printHeading.concat(appendString);
    }
    
    public static void replaceHeader(final String targetString,final String replaceString){
        
        printHeading = printHeading.replace(targetString, replaceString);
    }

	public static Boolean isContain(final String value){
	    
	    return stringCash.contains(value);
	}

	/**
	 * Method register the delimiter.
	 * 
	 * @param level1 first level split and default contain as |
	 * @param level2 second level split and default contain as :
	 */
    public static void registerDelemeter(final String level1, final String level2) {

        delimiterLevel1 = level1;
        delimiterLevel2 = level2;
    }

    public static void throwCommonUtilityException(final String message) throws Exception {

        throw new Exception(message);

    }

    private static String getKey(final String nextToken) {

        return nextToken.split(delimiterLevel2)[0];
    }

    private static String getValue(final String nextToken) {

        return nextToken.split(delimiterLevel2).length > 1 ? nextToken.split(delimiterLevel2)[1] : "NULL";
    }

    private static void validate(final String nextToken) throws Exception {

        if (!nextToken.contains(delimiterLevel2))
            throwCommonUtilityException("Message string " + delimiterLevel2 + nextToken + " not in the expected format.");

    }
    
    
    public static Date convertStringToSqlDate(final String value) {

        Calendar calander = Calendar.getInstance();
        calander.set(Calendar.YEAR, convertStringToInt(value.split("-")[0]));
        calander.set(Calendar.MONTH, convertStringToInt(value.split("-")[0]));
        calander.set(Calendar.DATE, convertStringToInt(value.split("-")[0]));

        final Date date = new Date(calander.getTimeInMillis());

        return date;
    }

    public static boolean convertStringToBoolean(final String value) {

        return value.equals("TRUE");
    }

    public static int convertStringToInt(final String value) {

        return Integer.parseInt(value);
    }

    public static long convertStringToLong(final String value) {

        return Long.parseLong(value);
    }
    
    public static double convertStringToDouble(final String value) {

        return Double.parseDouble(value);
    }

    public static Object convertStringToNull(final String value) {

        return value.equals("NULL") ? null : value;
    }

    public static String convertLongToString(final long value) {

        return String.valueOf(value);
    }

    public static String convertDoubleToString(final double value) {

        return String.valueOf(value);
    }

    public static String convertBooleanToString(final boolean value) {

        return value ? "TRUE" : "FALSE";
    }

    public static String convertNullToString(final Object value) {

        return value == null ? "NULL" : "NOTNULL";
    }

    public static String convertIntToString(final int value) {

        return String.valueOf(value);
    }
    
    public static java.util.Date convertStringToDate(final String value) {

        Calendar calander = Calendar.getInstance();
        final String[] dates = value.split("/");

        calander.set(Calendar.YEAR, convertStringToInt(dates[0].trim()));
        calander.set(Calendar.MONTH, convertStringToInt(dates[1].trim())-1);
        calander.set(Calendar.DATE, convertStringToInt(dates[2].trim()));

        final java.util.Date date = calander.getTime();

        return date;
    }

    public static java.util.Date convertStringToTime(final String value) throws ParseException {
        
    	final DateFormat format = new SimpleDateFormat("yyyy/MM/dd HH-mm-ss");
    	final java.util.Date date = format.parse(value);
    	
    	return date;
    }
    
    public static Boolean isStringDateEquals(final java.util.Date date,final String stringDate) {

        Calendar actualDate = Calendar.getInstance();
        actualDate.setTime(date);

        Calendar strDate = Calendar.getInstance();
        strDate.setTime(convertStringToDate(stringDate));
        
      return strDate.get(Calendar.YEAR) == actualDate.get(Calendar.YEAR)
      && strDate.get(Calendar.MONTH) == actualDate.get(Calendar.MONTH)
      && strDate.get(Calendar.DATE) == actualDate.get(Calendar.DATE);      
        
    }
    
    public static Timestamp convertStringToSqlTimeStamp(final String value) {

        Calendar calander = Calendar.getInstance();
        final String[] dates = value.split("-");
        int i = 0;

        calander.set(Calendar.YEAR, convertStringToInt(dates[i++]));
        calander.set(Calendar.MONTH, convertStringToInt(dates[i++]));
        calander.set(Calendar.DATE, convertStringToInt(dates[i++]));

        if (dates.length > i)
            calander.set(Calendar.HOUR, convertStringToInt(dates[i++]));
        if (dates.length > i)
            calander.set(Calendar.MINUTE, convertStringToInt(dates[i++]));
        if (dates.length > i)
            calander.set(Calendar.SECOND, convertStringToInt(dates[i++]));
        if (dates.length > i)
            calander.set(Calendar.MILLISECOND, convertStringToInt(dates[i++]));

        Timestamp date = new Timestamp(calander.getTime().getTime());

        return date;
    }

    public static String convertSQLTimeStampToStringDate(final Timestamp value) {

        Calendar calander = Calendar.getInstance();
        calander.setTime(value);


        return calander.get(Calendar.YEAR) + "-" + calander.get(Calendar.MONTH) + "-" + calander.get(Calendar.DATE) + "-"
      + calander.get(Calendar.HOUR) + "-" + calander.get(Calendar.MINUTE) + "-" + calander.get(Calendar.SECOND)+ "-" 
      + calander.get(Calendar.MILLISECOND);

    }

    public static String convertDateStringToFirstThreeComponent(final java.util.Date date) {

        //Default date format - MM/dd/yy
        final Format formatter=new SimpleDateFormat("yyyy/MM/dd");
        final String fromatedString = formatter.format(date);

        return fromatedString;
    }

    public static String convertCalandarDateToString(final Calendar date) {

        return convertIntToString(date.get(Calendar.YEAR)) + " - " 
            + convertIntToString(date.get(Calendar.MONTH)) + " - "
            + convertIntToString(date.get(Calendar.DATE));
    }
    
    public static String convertDateToString(final java.util.Date date) throws Exception {
        
        if(null == date)
            return convertNullToString(date);

        final Format formatter=new SimpleDateFormat("yyyy/MM/dd");
        final String fromatedString = formatter.format(date);
        
        return fromatedString;
    }
    

    public static String addDateByDays(final String date, final Integer numberOfDays) {

        final Timestamp tempDate = convertStringToSqlTimeStamp(date);
        final Calendar calander = Calendar.getInstance();
        calander.setTime(tempDate);
        calander.add(Calendar.DAY_OF_MONTH, numberOfDays);

        return calander.get(Calendar.YEAR) + "-" + calander.get(Calendar.MONTH) + "-" + calander.get(Calendar.DATE);
    }

    /**
     * Method use to collect priniting data.
     * 
     * @param printData Data pattern should contains patters <key>:<value>
     * @throws Exception
     */
    public static void addPrintBucket(final String printData) throws Exception {

        printString = printString.concat(printData + "|");
    }

    public static void print() throws Exception {

        if (printString.trim().length() != 0)
            print(printHeading, printString);

        printString = "";
        intend = 0;
    }
    
    /**
     * Method will only support the pattern key:<value>|key:<value>
     * 
     * @param stringPattern
     */
    public static void print(final String dataPattern) throws Exception {

        print(printHeading, dataPattern);
    }
    
    /**
     * Method will only support the pattern key:<value>|key:<value>
     * 
     * @param stringPattern
     */
    public static void print(final String heading, final String dataPattern) throws Exception {

        final StringTokenizer tokenizer = new StringTokenizer(dataPattern, "|");

        final String intendString = getIntendString();
        
        System.out.println(intendString + columnate(heading, 75));

        System.out.println(intendString + "############################################################################################################################################################################");
        System.out.println(intendString + "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
        System.out.println(intendString + "#                    Key                                                 #                         Value                                                                    #");
        System.out.println(intendString + "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------");

        while (tokenizer.hasMoreTokens()) {

            final String nextToken = tokenizer.nextToken();            
            final String tokenKey = getKey(nextToken);
            final String tokenValue = getValue(nextToken);

            System.out.println(intendString + "#" + columnate("<" + tokenKey + ">", rightColumn) + "             #" + columnate("[" + tokenValue + "]", leftColumn)
                + "                                    #");

            System.out.println(intendString + "---------------------------------------------------------------------------------------------------------------------------------------------------------------------------");

        }

        System.out.println(intendString + "############################################################################################################################################################################");

    }
    
    private static String getIntendString() {

        String intendString = "";

        for (int i = 0; i < intend; i++) {
            intendString = intendString.concat(" ");
        }

        return intendString;
    }

    private static String columnate(final String str, final int colsize) {

        String blanks = "                                                                                                      ";
        if (colsize > str.length())
            blanks = blanks.substring(0, colsize - str.length()) + str;

        if (colsize < str.length()) {
            int midleIndex = str.length() / 2;
            final String firstLine = str.substring(0, midleIndex);
            final String secondLine = str.substring(midleIndex, str.length());
            blanks = firstLine + "# \\n# " + secondLine + secondLine + (blanks + blanks).substring(0, rightColumn + leftColumn);
        }

        return blanks;
    }
    
    public static void reset() {

        delimiterLevel1 = "\\|";
        delimiterLevel2 = ":";
    }

    public static void hold(final int millisecond) throws InterruptedException {


        int sleepingBlocks = millisecond / 1000;

        for (int i = 1; i <= sleepingBlocks; i++) {

            System.out.println(i + ". Holding ... milliseconds " + 1000);
            Thread.sleep(1000);

        }

        System.out.println("Thread released.");

    }
    
    public static String append(final String contents, final String key, final String value) {

        return contents.concat(key + ":" + value + "|");
    }
    
    public static String replace(final String content, final String replacableValues) throws Exception {

        final String[] collection = content.split("\\|");
        final StringBuilder replacedString = new StringBuilder();

        for (final String keyValues : collection) {

            final String key = keyValues.split(":")[0];
            String value = keyValues.split(":")[1];

            if (replacableValues.contains(key)) {

                value = find(replacableValues, key);
            }

            replacedString.append(key + ":" + value + "|");

        }

        return replacedString.toString();

    }
    
    public static Boolean compare(final String actualString, final String matchinString) throws Exception {

        final StringTokenizer tokenizer = new StringTokenizer(matchinString, "|");
        Boolean isMatched = Boolean.FALSE;

        while (tokenizer.hasMoreTokens()) {

            final String token = tokenizer.nextToken();
            final String key = token.split(":")[0];
            final String actualValue = find(actualString, key);
            final String expectedValue = token.split(":")[1];

            print(key, "Actual:" + actualValue + "|Expected:" + expectedValue);
            isMatched = actualValue.equals(expectedValue);

            if (!isMatched)
                return isMatched;

        }

        return isMatched;

    }
    

}
